package net.wicp.tams.component.tools;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.tapestry5.Asset;
import org.apache.tapestry5.ioc.Configuration;
import org.apache.tapestry5.ioc.Messages;
import org.apache.tapestry5.ioc.services.CoercionTuple;
import org.apache.tapestry5.json.JSONArray;
import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.AssetSource;
import org.apache.tapestry5.services.Request;
import org.apache.tapestry5.services.RequestGlobals;
import org.apache.tapestry5.util.StringToEnumCoercion;
import org.apache.tapestry5.util.TextStreamResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.wicp.tams.common.web.EasyUiAssist;
import net.wicp.tams.commons.Result;
import net.wicp.tams.commons.apiext.JSONUtil;
import net.wicp.tams.commons.apiext.StringUtil;
import net.wicp.tams.commons.callback.IConvertValue;

public abstract class TapestryAssist {
	private static Logger logger = LoggerFactory.getLogger(TapestryAssist.class);

	/*****
	 * 返回TextStreamResponse
	 *
	 * @param opt
	 * @return
	 */
	public static TextStreamResponse getTextStreamResponse(Result opt) {
		return getTextStreamResponse(opt.retJsonObj().toJSONString());
	}

	/*****
	 * 返回TextStreamResponse
	 *
	 * @param jsonStr
	 *            json格式的字符串
	 * @return
	 */
	public static TextStreamResponse getTextStreamResponse(String jsonStr) {
		return new TextStreamResponse("text/html", jsonStr);
	}

	/*****
	 * 返回一个空的streamResponse
	 *
	 * @return
	 */
	public static TextStreamResponse getTextStreamResponseEmpty() {
		return new TextStreamResponse("text/html", EasyUiAssist.getJsonForGridEmpty());
	}

	/***
	 * 把tapestry的路径转为系统文件的路径,如果不存在相关文件就会抛出异常
	 *
	 * @param assetSource
	 * @param tPath
	 * @return
	 */
	public static String getResPathByTPath(AssetSource assetSource, String tPath) {
		if (assetSource == null || StringUtil.isNull(tPath)) {
			return "";
		}
		Asset asset = assetSource.getExpandedAsset(tPath);
		return asset.getResource().toURL().toString().replace("file:/", "");
	}

	/****
	 * 把JSONArray转成List,页按"index"域排序
	 *
	 * @param arry
	 * @param comp
	 *            比较对象
	 * @return
	 */
	public static List<JSONObject> getJSONObjectList(JSONArray arry, CompartorJson comp) {
		List<JSONObject> retObjList = new ArrayList<JSONObject>();
		if (arry == null || arry.length() == 0) {
			return retObjList;
		}
		for (int i = 0; i < arry.length(); i++) {
			JSONObject eleObject = arry.getJSONObject(i);
			retObjList.add(eleObject);
		}
		if (comp != null) {
			Collections.sort(retObjList, comp);
		}
		return retObjList;
	}

	public static List<JSONObject> getJSONObjectList(JSONArray arry) {
		return getJSONObjectList(arry, null);
	}

	/****
	 * 通过key得到国际化信息
	 *
	 * @param messages
	 * @param key
	 * @param param
	 * @return
	 */
	public static String LK(Messages messages, String key, Object... param) {
		if (StringUtil.isNull(key) || !messages.contains(key)) {
			return String.format(messages.get("common.hint.needI18n"), key); // 提示缺少国际化
		}
		return String.format(messages.get(key), param);
	}

	/****
	 * 得到请求的参数，如果是数组则对象是JSONArray,否则是String
	 *
	 * @param request
	 * @return
	 */
	public static JSONObject packParams(Request request) {
		JSONObject retobj = new JSONObject();
		if (request == null) {
			return retobj;
		}
		List<String> keys = request.getParameterNames();
		if (CollectionUtils.isNotEmpty(keys)) {
			for (String key : keys) {
				if (key.endsWith("[]")) {
					String[] objs = request.getParameters(key);
					if (ArrayUtils.isNotEmpty(objs)) {
						JSONArray ary = new JSONArray();
						for (int i = 0; i < objs.length; i++) {
							ary.put(objs[i]);
						}
						retobj.put(key.replace("[]", ""), ary);
					}
				} else {
					retobj.put(key, request.getParameter(key));
				}
			}
		}
		return retobj;
	}

	/****
	 * 得到参数的值，如果是数组则只取第一个元素
	 *
	 * @param params
	 * @param name
	 * @return
	 */
	public static String getParam(JSONObject params, String name) {
		if (!params.has(name)) {
			return null;
		}
		Object obj = params.opt(name);
		if (obj == null) {
			return null;
		}
		if (obj instanceof JSONArray) {
			JSONArray temp = (JSONArray) obj;
			return temp.getString(0);
		} else {
			return String.valueOf(obj);
		}
	}

	/***
	 * 得到参数的多值，如果只有一个元素只返回一个元素的JSONArray
	 *
	 * @param params
	 * @param name
	 * @return
	 */
	public static JSONArray getParams(JSONObject params, String name) {
		if (!params.has(name)) {
			return null;
		}
		Object obj = params.opt(name);
		if (obj == null) {
			return null;
		}
		if (obj instanceof JSONArray) {
			JSONArray temp = (JSONArray) obj;
			return temp;
		} else {
			JSONArray temp = new JSONArray(obj);
			return temp;
		}
	}

	@SuppressWarnings("rawtypes")
	public static JSONObject buildSelGroupInit(List<?> allObj, List<String> selIds, String[] aliasTitles,
			Map<String, IConvertValue> convertsMap) {
		JSONObject ret = new JSONObject();
		if (CollectionUtils.isEmpty(allObj)) {
			ret.put("data", new JSONArray());
			ret.put("sel", new JSONArray());
			return ret;
		}
		String dataStr = JSONUtil.getJsonForListAlias(allObj, aliasTitles, convertsMap);
		JSONArray dataary = new JSONArray(dataStr);
		ret.put("data", dataary);
		JSONArray selId = new JSONArray();
		if (CollectionUtils.isNotEmpty(selIds)) {
			for (Object ele : selIds) {// 请用Object,因为有可能是整形传过来
				boolean include = false;
				for (int i = 0; i < dataary.length(); i++) {
					JSONObject obj = dataary.getJSONObject(i);
					if (obj.getString("id").equals(String.valueOf(ele))) {
						include = true;
						break;
					}
				}
				if (include) {
					selId.put(String.valueOf(ele));
				}
			}
		}
		ret.put("sel", selId);
		return ret;
	}

	/***
	 * 把数据转成SelGroup可以识别的数据
	 *
	 * @param allObj
	 * @param selIds
	 * @return
	 */
	public static JSONObject buildSelGroupInit(List<?> allObj, List<String> selIds) {
		return buildSelGroupInit(allObj, selIds, null, null);
	}

	/****
	 * 把请求字段封装到Bean中
	 *
	 * @param clazz
	 * @param request
	 * @return
	 */
	public static <T> T getBeanFromPage(Class<T> clazz, Request request) {
		try {
			T retobj = clazz.newInstance();
			JSONObject packParams = packParams(request);
			if (packParams.length() == 0) {
				return retobj;
			}
			for (String key : packParams.keys()) {
				StringUtil.packObj(retobj, key, packParams.getString(key));
			}
			return retobj;
		} catch (Exception e) {
			throw new IllegalAccessError("request转为业务对象时异常" + e.getMessage());
		}

	}

	public static <T> T getBeanFromPage(Class<T> clazz, RequestGlobals requestGlob) {
		return getBeanFromPage(clazz, requestGlob.getRequest());
	}

	/****
	 * 把请求封装为一个Map
	 * 
	 * @param request
	 * @return
	 */
	public static Map<String, Object> getParameterMap(Request request) {
		List<String> names = request.getParameterNames();
		Map<String, Object> paramsMap = new HashMap<String, Object>();
		StringBuilder sb = new StringBuilder();
		for (String name : names) {
			Object[] values = request.getParameters(name);
			if (values != null) {
				String key = name.replaceAll("\\[\\]", "");
				if (values.length == 1) {
					paramsMap.put(key, values[0]);
				} else {
					paramsMap.put(key, values);
				}
				String v = Arrays.asList(values).toString();
				sb.append("key = ").append(key).append(" , value = ").append(v).append("\r\n");
			}
		}
		logger.debug("The parameters:\r\n" + sb.toString());
		return paramsMap;
	}

	/***
	 * 添加枚举类的转换器
	 * 
	 * @param configuration
	 * @param enumType
	 */
	public static <T extends Enum> void addEnumCoercion(Configuration<CoercionTuple> configuration, Class<T> enumType) {
		configuration.add(CoercionTuple.create(String.class, enumType, StringToEnumCoercion.create(enumType)));
	}

}
